package com.du.limiting.sentinel.aop;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.annotation.aspectj.AbstractSentinelAspectSupport;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSONObject;
import com.du.limiting.sentinel.component.RequestWrapper;
import com.du.limiting.sentinel.model.User;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.*;
import java.util.Map;

/**
 * @author dujunguang
 * @date 2022/3/1 14:41
 * @description: Sentinel 资源定义
 **/
@Component("sentinelAspect")
@Aspect
@Slf4j
@ConditionalOnProperty(prefix = "sentinel",name = "switch",havingValue = "true")
public class SentinelResourceAspect extends AbstractSentinelAspectSupport {

    int i;

    /**
     * 定义切点
     */
    @Pointcut("@annotation(com.du.limiting.sentinel.aop.DiySentinelResource)")
    public void pointCut() {

    }

    @Around(value = "pointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Method method = ((MethodSignature) point.getSignature()).getMethod();
        // 资源注解获取资源名
        DiySentinelResource diySentinelResource = method.getAnnotation(DiySentinelResource.class);
        String resourceName = diySentinelResource.value();
//        SentinelResource annotation = method.getAnnotation(SentinelResource.class);
//        InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
//        Field hField = invocationHandler.getClass().getDeclaredField("memberValues");
//        hField.setAccessible(true);
//        Map memberValues = (Map) hField.get(invocationHandler);
//        memberValues.put("value", resourceName);

//        Class<SentinelResource> sentinelResourceClass = SentinelResource.class;
//        Field field = sentinelResourceClass.getDeclaredField("value");
//        field.setAccessible(true);
//        field.set(sentinelResourceClass,);

        Object[] args = point.getArgs();
        String body = JSONObject.toJSONString(args[0]);
        Object object = JSONObject.parseObject(body, args[0].getClass());
        // 封装request，获取请求body
        if (!(object instanceof User)) {
            return point.proceed();
        }

        User user = JSONObject.parseObject(body, User.class);
        Entry entry = null;
        try {
            entry = SphU.entry(resourceName, EntryType.IN, 1, user.getName());
            return point.proceed();
        } catch (BlockException ex) {
            throw ex;
//            return handleBlockException(point, annotation, ex);
        } catch (Throwable ex) {
//            Class<? extends Throwable>[] exceptionsToIgnore = annotation.exceptionsToIgnore();
//            if (exceptionsToIgnore.length > 0 && exceptionBelongsTo(ex, exceptionsToIgnore)) {
//                throw ex;
//            }
//            if (exceptionBelongsTo(ex, annotation.exceptionsToTrace())) {
//                traceException(ex);
//                return handleFallback(point, annotation, ex);
//            }
            throw ex;
        } finally {
            if (entry != null) {
                entry.exit(1, user.getName());
            }
        }


    }

    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        Class<SentinelResource> sentinelResourceClass = SentinelResource.class;
        Constructor<?>[] declaredConstructors = sentinelResourceClass.getDeclaredConstructors();


        System.out.println();
    }



}


























